﻿namespace PropOnline.Errors
{
    using System;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Configuration.Provider;
    using System.Data;
    using System.Globalization;
    using System.Web.Management;
    using MySql.Data.MySqlClient;

    public class MySqlWebEventProvider : WebEventProvider
    {
        private string connectionString;

        public override void Initialize(string name, NameValueCollection config)
        {
            // Verify that config isn't null
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // Assign the provider a default name if it doesn't have one
            if (string.IsNullOrEmpty(name))
            {
                name = "MySqlWebEventProvider";
            }

            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "MySql Web event provider");
            }

            // Call the base class's Initialize method
            base.Initialize(name, config);

            // Initialize _LogFileName and make sure the path
            // is app-relative
            string connectionStringName = config["connectionStringName"];
            if (string.IsNullOrEmpty(connectionStringName))
            {
                throw new ProviderException("Missing connectionStringName attribute");
            }

            if (ConfigurationManager.ConnectionStrings[connectionStringName] == null)
            {
                throw new ArgumentException("No connectionString was found with the name " + connectionStringName);
            }

            this.connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
            config.Remove("connectionStringName");

            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!string.IsNullOrEmpty(attr))
                {
                    throw new ProviderException("Unrecognized attribute: " + attr);
                }
            }
        }

        public override void ProcessEvent(WebBaseEvent raisedEvent)
        {
            var connection = new MySqlConnection();
            connection.ConnectionString = this.connectionString;
            try
            {
                connection.Open();
                var cmd = new MySqlCommand();
                cmd.Connection = connection;
                cmd.CommandText = "webevent_logevent";
                cmd.CommandType = CommandType.StoredProcedure;

                cmd.Parameters.AddWithValue("@EventId", raisedEvent.EventID.ToString("N", CultureInfo.InvariantCulture));
                cmd.Parameters["@EventId"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventTimeUtc", raisedEvent.EventTimeUtc);
                cmd.Parameters["@EventTimeUtc"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventTime", raisedEvent.EventTime);
                cmd.Parameters["@EventTime"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventType", raisedEvent.GetType().ToString());
                cmd.Parameters["@EventType"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventSequence", raisedEvent.EventSequence);
                cmd.Parameters["@EventSequence"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventOccurrence", raisedEvent.EventOccurrence);
                cmd.Parameters["@EventOccurrence"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventCode", raisedEvent.EventCode);
                cmd.Parameters["@EventCode"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@EventDetailCode", raisedEvent.EventDetailCode);
                cmd.Parameters["@EventDetailCode"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@Message", raisedEvent.Message);
                cmd.Parameters["@Message"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@ApplicationPath", WebBaseEvent.ApplicationInformation.ApplicationPath);
                cmd.Parameters["@ApplicationPath"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@ApplicationVirtualPath", WebBaseEvent.ApplicationInformation.ApplicationVirtualPath);
                cmd.Parameters["@ApplicationVirtualPath"].Direction = ParameterDirection.Input;

                cmd.Parameters.AddWithValue("@MachineName", WebBaseEvent.ApplicationInformation.MachineName);
                cmd.Parameters["@MachineName"].Direction = ParameterDirection.Input;

                WebRequestInformation webRequestInformation = null;
                if (raisedEvent is WebRequestEvent)
                {
                    webRequestInformation = ((WebRequestEvent)raisedEvent).RequestInformation;
                }
                else
                {
                    if (raisedEvent is WebRequestErrorEvent)
                    {
                        webRequestInformation = ((WebRequestErrorEvent)raisedEvent).RequestInformation;
                    }
                    else
                    {
                        if (raisedEvent is WebErrorEvent)
                        {
                            webRequestInformation = ((WebErrorEvent)raisedEvent).RequestInformation;
                        }
                        else
                        {
                            if (raisedEvent is WebAuditEvent)
                            {
                                webRequestInformation = ((WebAuditEvent)raisedEvent).RequestInformation;
                            }
                        }
                    }
                }

                cmd.Parameters.AddWithValue("@RequestUrl", ((webRequestInformation != null) ? webRequestInformation.RequestUrl : string.Empty));
                cmd.Parameters["@RequestUrl"].Direction = ParameterDirection.Input;

                Exception ex = null;
                if (raisedEvent is WebBaseErrorEvent)
                {
                    ex = ((WebBaseErrorEvent)raisedEvent).ErrorException;
                }

                cmd.Parameters.AddWithValue("@ExceptionType", (ex != null) ? ex.GetType().ToString() : string.Empty);
                cmd.Parameters["@ExceptionType"].Direction = ParameterDirection.Input;

                var text = raisedEvent.ToString();
                if (text.Length > 1073741823)
                {
                    text = text.Substring(0, 1073741823);
                }

                cmd.Parameters.AddWithValue("@Details", text);
                cmd.Parameters["@Details"].Direction = ParameterDirection.Input;

                cmd.ExecuteNonQuery();
            }
            catch (Exception)
            {
            }
            finally
            {
                try 
                { 
                    connection.Close(); 
                }
                catch (Exception)
                {
                }
            }
        }

        public override void Flush()
        {
        }

        public override void Shutdown()
        {
        }
    }
}